from rest_framework.decorators import api_view, permission_classes, action
from rest_framework.views import Response, Request
from rest_framework.permissions import IsAuthenticated, IsAdminUser, DjangoModelPermissions
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet

from utils.exceptions import InvalidPassword
from utils.permissions import CrudModelPermissions
from .models import UserProfile
from django.contrib.auth import get_user_model
from .serializers import UserSerializer, PermSerializer, RoleSerializer
from django_filters.rest_framework.backends import DjangoFilterBackend
from rest_framework.filters import SearchFilter
from django.http.response import Http404
from django.contrib.auth.models import Group, Permission, ContentType


class RoleViewSet(ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = RoleSerializer

    @action(detail=True, url_path='perms')  # GET, pk /users/pk/perms
    def get_all_perms(self, request, pk=None):
        obj = self.get_object()
        data = RoleSerializer(obj).data  # dict
        data['allPerms'] = PermViewSet.queryset.values('id', 'name')
        return Response(data)


_exclude_contenttypes = [d.get('id') for d in ContentType.objects.exclude(model__in=[
    'logentry',
    'group',
    'permission',
    'contenttype',
    'session',
]).values('id')]


class PermViewSet(ReadOnlyModelViewSet):  # list retrive 没有修改的功能
    queryset = Permission.objects.filter(content_type__in=_exclude_contenttypes)
    serializer_class = PermSerializer


class UserViewSet(ModelViewSet):
    # permission_classes = [IsAdminUser,IsAuthenticated]
    permission_classes = [CrudModelPermissions] #只对当前model的增删该查权限做限制
    queryset = UserProfile.objects.all()
    #     get_user_model().objects.all()
    serializer_class = UserSerializer
    filter_backends = [SearchFilter]
    search_fields = ['username', 'email', 'phone']

    def update(self, request, *args, **kwargs):
        request.data.pop('username', None)
        request.data.pop('password', None)
        return super().update(request, *args, **kwargs)

    def get_object(self):
        if self.request.method.lower() != 'get':
            # 这里使用is_superuser更合理

            if self.kwargs.get('pk') == '1' or self.kwargs.get('pk') == 1:
                raise Http404
                # self.request.data query_params
        return super().get_object()

    @action(['GET'], detail=False, url_path='whoami')  # users/mgr/whoami
    def whoami(self, request):
        return Response({
            'id': request.user.id,
            'username': request.user.username
        })

    @action(detail=True, methods=['post'], url_path='setpwd')
    def set_password(self, request, pk=None):  # /users/pk/setpwd/
        user: UserProfile = self.get_object()
        # print('*' * 30)
        # print(user)
        # print('*' * 30)
        # user:UserProfile = request.user
        # user.is_superuser  判断是否是管理员
        try:
            oldpwd = request.data['oldPassword']
            newpwd = request.data['password']
            if user.check_password(oldpwd):
                user.set_password(newpwd)
                user.save()
                return Response(status=201)
            else:
                raise InvalidPassword
        except Exception as e:
            raise InvalidPassword

    # @action(detail=True, methods=['GET'], url_path='roles')
    # def roles(self, request, pk=None):  # /users/mgr/2/roles/ GET
    #     print('*'*30)
    #     user = self.get_object()
    #     print(user)
    #     print('*' * 30)
    #     data = UserSerializer(user).data
    #     data['roles'] = [r.get('id') for r in user.groups.values('id')]
    #     data['allRoles'] = Group.objects.values('id', 'name')
    #     return Response(data)

    @action(detail=True, methods=['GET'], url_path='roles')  # /users/mgr/2/roles
    def roles(self, request, pk=None):
        user: UserProfile = self.get_object()
        print('*' * 30)
        print(user)
        print('*' * 30)
        data = UserSerializer(user).data
        data['allRoles'] = Group.objects.values('id', 'name')
        data['roles'] = user.groups.values('id')
        return Response(data)

    # action(['POST'], detail=True, url_path='')           # /users/mgr/2/roles
    @roles.mapping.put
    def set_roles(self, request, pk=None):
        user = self.get_object()
        print(request.data, '############')  # ????????  {'groups': [1]}
        groups = request.data.get('groups', [])
        user.groups.set(groups)
        # user.groups.set({})
        return Response(status=201)

    # serializer = PasswordSerializer(data=request.data)
    # if serializer.is_valid():
    #     user.set
    # filter_fields = ['username']
    # def list(self, request, *args, **kwargs):
    #
    #     return super().list(request, *args, **kwargs)

    # def get_queryset(self):
    #     qs = super().get_queryset()
    #     username = self.request.query_params.get('username', '')
    #     if username:
    #         qs = qs.filter(username__icontains=username)
    #     return qs


# Create your views here.

class MenuItem(dict):
    def __init__(self, id, itemName, path=None):
        super().__init__()
        self.id = id
        self.itemName = itemName
        self.path = path
        self.children = []

    def __setattr__(self, key, value):
        self[key] = value

    def __getattr__(self, key):
        return self[key]

    def append(self, sub):
        self.children.append(sub)
        return self


item = MenuItem(1, '用户管理', '/users')
sub = MenuItem(2, '用户列表', '/users')
item.children.append(sub)


@api_view(['GET'])
# @permission_classes([IsAuthenticated])  # TODO ISAdminUser
def menulist(request: Request):
    menulist = {'items': []}
    # print(request)
    # print(request.user)
    # print(request.user.is_superuser)
    # print("++++++++++++++++")
    if request.user.is_superuser:
        item = MenuItem(1, '用户管理')
        menulist['items'].append(item)
        item.append(MenuItem(2, '用户列表', '/users/'))
        item.append(MenuItem(3, '角色列表', '/users/roles/'))
        item.append(MenuItem(4, '权限列表', '/users/perms/'))

    if request.user.has_perm('user.view_userprofile'):
        item9 = MenuItem(91, 't')
        item9.append(MenuItem(92, 't1', '/users/'))
        item9.append(MenuItem(93, 't2', '/users/roles/'))
        item9.append(MenuItem(94, 't3', '/users/perms/'))
        menulist['items'].append(item9)
    return Response(menulist)


@api_view(['GET', 'POST'])
def test(request: Request):
    # jwt如果成功，user是非匿名的user的实例，失败匿名用户实例
    # 成功 token，失败None
    return Response()
